#ifndef __SE_DICTIONARY_HPP__
#define __SE_DICTIONARY_HPP__

#include "Singleton.hpp"
#include "json.hpp"

#include <vector>
#include <map>
#include <set>
#include <string>
#include <memory>

namespace se {

// 字典类
class Dictionary final: public Singleton<Dictionary> {
    friend class Singleton<Dictionary>;
public:  // 公有函数成员
    /**
     * @brief 使用json文件初始化字典
     * @param dictionaryFileName 字典文件的路径
     * @param indexFileName 索引文件的路径
     */
    void dictionaryInitialize(const std::string &dictionaryFileName, const std::string &indexFileName);

    /**
     * @brief 查询与keyword相关联的所有单词
     * 
     * @param keyword 要查询的单词
     * @return std::shared_ptr<std::map<std::string, int32_t>> 返回相关联的所有单词以及频率
     */
    std::shared_ptr<std::map<std::string, int32_t>> query(const std::string &keyword);

    /**
     * @brief 将对象转换成对应的字符串形式
     * 
     * @return std::string 
     */
    std::string toString() const;

    /**
     * @brief 获取两个字符串/单词的最小编辑距离
     * 
     * @param lhs 左操作数
     * @param rhs 右操作数
     * @return int32_t 最小编辑距离 
     */
    static int32_t getEditDistance(const std::string &lhs, const std::string &rhs);

private:  // 私有函数成员
    Dictionary();

    /**
     * @brief 从文件中读取json
     * 
     * @param fileName json文件名
     * @return nlohmann::json 
     */
    static nlohmann::json getJsonFromFile(const std::string &fileName);

private:  // 私有数据成员
    std::vector<std::pair<std::string, int32_t>> _dictionary;  // 字典 <单词，出现次数>
    std::map<std::string, std::set<int32_t>> _index;  // 索引 <key，在字典中出现的行号集合>
};

}  // namespace se

#endif
